package com.netty.test.controller;

import com.netty.test.bean.HttpResult;
import com.netty.test.service.BackendHandler;
import com.netty.test.service.DispatcherOkHttpService;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import top.hserver.core.interfaces.HttpRequest;
import top.hserver.core.interfaces.HttpResponse;
import top.hserver.core.ioc.annotation.Autowired;
import top.hserver.core.ioc.annotation.Controller;
import top.hserver.core.ioc.annotation.RequestMapping;
import top.hserver.core.server.handlers.BuildResponse;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author hxm
 */
@Controller
public class ProxyController {

    @Autowired
    private DispatcherOkHttpService dispatcherOkHttpService;

    @RequestMapping("/proxy1/{p}")
    public void proxy1(HttpRequest request, HttpResponse response) {
        String nettyUri = request.getNettyUri();
        String replace = nettyUri.replace("/proxy1/", "");
        String url = "http://127.0.0.1:8888/" + replace;
        HttpResult httpResult = dispatcherOkHttpService.request(url, request);
        httpResult.getHeaders().forEach(response::setHeader);
        switch (httpResult.getRespType()) {
            case 重定向类型:
                response.redirect(httpResult.getLocation());
                break;
            case 文本类型:
                response.sendText(new String(httpResult.getContent()));
                break;
            case JSON类型:
                response.sendJsonString(new String(httpResult.getContent()));
                break;
            case HTML类型:
                response.sendHtml(new String(httpResult.getContent()));
                break;
            default:
                request.getCtx().writeAndFlush(dispatcherOkHttpService.getFullHttpResponse(httpResult));
                break;
        }

    }


//    ---------------------------------------------------------------------


    private static Channel CHANNEL;

    @RequestMapping("/proxy/{p}")
    public void proxy(HttpRequest request, HttpResponse response) {
        //用户自己调用ctx
        response.isProxy(true);
        String nettyUri = request.getNettyUri();
        /**
         * 调用的uri 和host:port
         */
        String uri = nettyUri.replace("/proxy", "");
        SocketAddress socketAddress = new InetSocketAddress("hserver.top", 8099);
        FullHttpRequest nettyRequest = request.getNettyRequest();
        nettyRequest.setUri(uri);
        ChannelHandlerContext ctx = request.getCtx();
        Bootstrap b = new Bootstrap();
        b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);
        b.group(ctx.channel().eventLoop());
        b.channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel ch) {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(new HttpClientCodec());
                pipeline.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
                pipeline.addLast(new BackendHandler(ctx));
            }
        });
        //走缓存的，你是多个ip地址，就换map存
        if (CHANNEL != null && CHANNEL.isActive()) {
            CHANNEL.writeAndFlush(nettyRequest);
        } else {
            final AtomicInteger count = new AtomicInteger(0);
            b.connect(socketAddress).addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (future.isSuccess()) {
                        if (CHANNEL == null) {
                            CHANNEL = future.channel();
                        }
                        future.channel().writeAndFlush(nettyRequest);
                    } else {
                        if (count.incrementAndGet() > 3) {
                            CHANNEL = null;
                            ctx.writeAndFlush(BuildResponse.buildString("异常"));
                            future.channel().close();
                        } else {
                            CHANNEL = null;
                            b.connect(socketAddress).addListener(this);
                        }
                    }
                }
            });
        }
    }
}
